package validatorV2

import (
	"errors"
	"gitee.com/xlizy/common-go/base/enums/common_error"
	"gitee.com/xlizy/common-go/base/response"
	"github.com/go-playground/locales/en"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	pv "github.com/go-playground/validator/v10"
	enTranslations "github.com/go-playground/validator/v10/translations/en"
	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
	"reflect"
	"regexp"
	"sync"
)

const (
	locale = "chinese"
)

type CusVal struct {
	Name string
	Func pv.Func
}

var once sync.Once

type valIns struct {
	validate   *pv.Validate
	translator ut.Translator
}

var _valIns *valIns

func Init(cusVal ...CusVal) *valIns {
	once.Do(func() {
		_valIns = new(valIns)
		chinese := zh.New()
		english := en.New()
		//设置国际化翻译器
		uni := ut.New(chinese, chinese, english)
		//设置验证器
		_valIns.validate = pv.New()
		//根据参数取翻译器实例
		_valIns.translator, _ = uni.GetTranslator(locale)
		//翻译器注册到validator
		switch locale {
		case "chinese":
			_ = zhTranslations.RegisterDefaultTranslations(_valIns.validate, _valIns.translator)
			//使用fld.Tag.Get("comment")注册一个获取tag的自定义方法
			_valIns.validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
				return "[" + fld.Tag.Get("comment") + "]"
			})
			//自定义翻译器
			_ = _valIns.validate.RegisterTranslation("email", _valIns.translator, func(ut ut.Translator) error {
				return ut.Add("email", "{0}不符合邮箱规则", true)
			}, func(ut ut.Translator, fe pv.FieldError) string {
				t, _ := ut.T("email", fe.Field())
				return t
			})

			//自定义验证方法
			_ = _valIns.validate.RegisterValidation("valid_username", func(fl pv.FieldLevel) bool {
				matched, _ := regexp.Match("^[a-z]{6,30}$", []byte(fl.Field().String()))
				return matched
			})
			//自定义翻译器
			_ = _valIns.validate.RegisterTranslation("valid_username", _valIns.translator, func(ut ut.Translator) error {
				return ut.Add("valid_username", "{0}输入格式不正确或长度不符", true)
			}, func(ut ut.Translator, fe pv.FieldError) string {
				t, _ := ut.T("valid_username", fe.Field())
				return t
			})

			if cusVal != nil {
				for _, cus := range cusVal {
					_ = _valIns.validate.RegisterValidation(cus.Name, cus.Func)
					_ = _valIns.validate.RegisterTranslation(cus.Name, _valIns.translator, func(ut ut.Translator) error {
						return ut.Add(cus.Name, "{0}格式不正确", true)
					}, func(ut ut.Translator, fe pv.FieldError) string {
						t, _ := ut.T(cus.Name, fe.Field())
						return t
					})
				}
			}

		case "english":
			_ = enTranslations.RegisterDefaultTranslations(_valIns.validate, _valIns.translator)
			_valIns.validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
				return "[" + fld.Tag.Get("en_comment") + "]"
			})
		}
	})
	return _valIns
}

func ValidParams(params interface{}) *response.Response {
	valid := _valIns.validate
	trans := _valIns.translator
	err := valid.Struct(params)
	//如果数据效验不通过，则将所有err以切片形式输出
	if err != nil {
		var errs pv.ValidationErrors
		errors.As(err, &errs)
		sliceErrs := make([]string, 0)
		for _, e := range errs {
			//使用validator.ValidationErrors类型里的Translate方法进行翻译
			sliceErrs = append(sliceErrs, e.Translate(trans))
		}
		return response.Error(common_error.RequestArgumentNotValid, sliceErrs)
	}
	return response.Succ()
}
